package util;

import java.util.List;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

	private final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

	private Configuration configuration;

	private org.hibernate.SessionFactory sessionFactory;

	public static Properties getDefaultProperties() {
		Properties properties = new Properties();
		/*
		 * 以下加入各种配置信息
		 * 作用为：替代hibernate.cfg.xml
		 */
		properties.setProperty(
						"hibernate.connection.url",
						"jdbc:mysql://localhost:3306/hibernate_study?useUnicode=true&characterEncoding=UTF8");
		properties.setProperty("hibernate.connection.driver_class",
				"com.mysql.jdbc.Driver");
		/*
		 * com.p6spy.engine.spy.P6SpyDriver可以加个驱动中间层
		 * 用于显示sql窜中的"?"的具体值
		 */
		properties.setProperty("hibernate.connection.username", "root");
		properties.setProperty("hibernate.connection.password", "root");
		properties.setProperty("hibernate.dialect",
						"org.hibernate.dialect.MySQLDialect");
		properties.setProperty("hibernate.transaction.factory_class",
				"org.hibernate.transaction.JDBCTransactionFactory");
		properties.setProperty("hibernate.cache.provider_class",
				"org.hibernate.cache.NoCacheProvider");
		properties.setProperty("hibernate.cache.use_second_level_cache", "false");
		properties.setProperty("hibernate.show_sql", "true");
		properties.setProperty("hibernate.format_sql", "true");
		properties.setProperty("hibernate.hbm2ddl.auto", "create");// 不耗用，不如自己SchemaExport.drop/create
		properties.setProperty("hibernate.jdbc.batch_size", "50");
		
		return properties;
	}

	@SuppressWarnings("unchecked")
	private HibernateUtil(List<Class> classes) {
		setConfiguration(HibernateUtil.getDefaultProperties(), classes);
		sessionFactory = configuration.buildSessionFactory();
	}

	public Session getSession() throws HibernateException {

		Session session = (Session) threadLocal.get();

		if (session == null || !session.isOpen()) {
			if (sessionFactory == null) {
				rebuildSessionFactory();
			}
			session = (sessionFactory != null) ? sessionFactory.openSession()
					: null;
			threadLocal.set(session);
		}


		return session;
	}
	
	@SuppressWarnings("unchecked")
	public static HibernateUtil instance(List<Class> classes) {
		return new HibernateUtil(classes);
	}

	public void rebuildSessionFactory() {
		try {
			sessionFactory = configuration.buildSessionFactory();
		} catch (Exception e) {
			System.err.println("%%%% Error Creating SessionFactory %%%%");
			e.printStackTrace();
		}
	}

	public void closeSession() throws HibernateException {
		Session session = (Session) threadLocal.get();
		threadLocal.set(null);

		if (session != null) {
			session.close();
		}
	}

	public org.hibernate.SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	@SuppressWarnings("unchecked")
	public void setConfiguration(Properties properties,List<Class> classes) {
		configuration = new Configuration().setProperties(properties);
		
		for (Class clazz : classes) {
			configuration.addClass(clazz);
		}
		
		sessionFactory = null;
	}

	public Configuration getConfiguration() {
		return configuration;
	}

}
